<template>
  <div class="markdown-container">
    <!-- 下载按钮 -->
    <button class="download-btn" @click="downloadPDF">
      <i class="fa fa-download mr-2"></i>下载 PDF
    </button>

    <!-- Markdown 内容区域 -->
    <div class="markdown-content" v-html="sanitizedHtml" ref="contentRef"></div>
  </div>
</template>

<script setup>
import { computed, ref, onMounted, nextTick, watch, onUnmounted } from 'vue'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import html2pdf from 'html2pdf.js'

// 配置 Marked 解析器以支持 Mermaid 语法
marked.setOptions({
  breaks: true,
  gfm: true,
  plugins: [
    {
      // 自定义渲染器处理 Mermaid 代码块
      code: (code, language) => {
        if (language === 'mermaid') {
          const containerId = `mermaid-${Date.now()}-${Math.random().toString(36).substring(2, 10)}`
          return `
            <div class="mermaid-container" data-mermaid-code="${encodeURIComponent(code)}" data-mermaid-id="${containerId}">
              <div id="${containerId}" class="mermaid-rendered"></div>
            </div>
          `
        }
        return `<pre><code>${code}</code></pre>`
      }
    }
  ]
})

const props = defineProps({
  content: {
    type: String,
    required: true,
    default: ''
  },
  fileName: {
    type: String,
    default: 'markdown-document'
  }
})

const contentRef = ref(null)
const isMermaidLoaded = ref(false)
const mermaidRenderers = ref([]) // 存储渲染器实例，用于销毁时清理

// 转换 Markdown 并清理 HTML
const sanitizedHtml = computed(() => {
  if (!props.content) return ''
  const html = marked(props.content)
  return DOMPurify.sanitize(html)
})

// 下载 PDF 功能（等待图表渲染完成后执行）
const downloadPDF = async () => {
  if (!contentRef.value || !isMermaidLoaded.value) return

  // 等待 DOM 更新完成（确保图表已渲染）
  await nextTick()

  const element = contentRef.value
  const options = {
    margin: 15,
    filename: `${props.fileName}.pdf`,
    image: { type: 'jpeg', quality: 0.95 },
    html2canvas: {
      scale: 2,
      useCORS: true,
      logging: false,
      allowTaint: true // 允许跨域资源
    },
    jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
  }

  html2pdf().from(element).set(options).save()
}

// 动态加载 Mermaid 库
onMounted(async () => {
  // 加载 Font Awesome
  await loadExternalResource('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css', 'link')

  // 加载 Mermaid
  if (!window.mermaid) {
    await loadExternalResource('https://cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js', 'script')
    // 配置 Mermaid 主题和选项
    window.mermaid.initialize({
      startOnLoad: false,
      theme: 'default',
      securityLevel: 'loose' // 允许渲染
    })
    isMermaidLoaded.value = true
    renderAllMermaidCharts()
  } else {
    isMermaidLoaded.value = true
    renderAllMermaidCharts()
  }
})

// 监听内容变化并重新渲染图表
watch(() => props.content, () => {
  if (isMermaidLoaded.value) {
    // 先清理旧渲染器
    cleanupMermaidRenderers()
    renderAllMermaidCharts()
  }
})

// 组件卸载时清理资源
onUnmounted(() => {
  cleanupMermaidRenderers()
})

// 清理 Mermaid 渲染器
function cleanupMermaidRenderers() {
  mermaidRenderers.value.forEach(renderer => {
    if (renderer) {
      renderer.clear()
    }
  })
  mermaidRenderers.value = []
}

// 工具函数：加载外部资源
function loadExternalResource(src, type) {
  return new Promise((resolve, reject) => {
    const el = type === 'script'
        ? document.createElement('script')
        : document.createElement('link')

    el.onload = resolve
    el.onerror = reject
    if (type === 'script') {
      el.src = src
      document.head.appendChild(el)
    } else {
      el.href = src
      el.rel = 'stylesheet'
      document.head.appendChild(el)
    }
  })
}

// 渲染所有 Mermaid 图表
function renderAllMermaidCharts() {
  const mermaidContainers = document.querySelectorAll('.mermaid-container')
  mermaidContainers.forEach(container => {
    const code = decodeURIComponent(container.getAttribute('data-mermaid-code') || '')
    const id = container.getAttribute('data-mermaid-id')

    if (!code || !id) return

    // 创建新的渲染器实例
    const renderer = window.mermaid.createRenderer()
    mermaidRenderers.value.push(renderer)

    renderer.render(id, code, (svg) => {
      const targetElement = document.getElementById(id)
      if (targetElement) {
        targetElement.innerHTML = svg
      }
    }, (error) => {
      console.error('Mermaid 渲染错误:', error)
      const targetElement = document.getElementById(id)
      if (targetElement) {
        targetElement.innerHTML = `<div class="mermaid-error">渲染失败: ${error.message}</div>`
      }
    })
  })
}
</script>

<style>
.markdown-container {
  position: relative;
}

.download-btn {
  position: sticky;
  top: 20px;
  right: 20px;
  z-index: 100;
  background-color: #007BFF;
  color: white;
  border: none;
  border-radius: 4px;
  padding: 8px 16px;
  font-size: 14px;
  cursor: pointer;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  display: flex;
  align-items: center;
  margin-bottom: 16px;
}

.download-btn:hover {
  background-color: #0056b3;
}

.markdown-content {
  line-height: 1.6;
  word-wrap: break-word;
  overflow-wrap: break-word;
}

/* Mermaid 图表样式 */
.mermaid-container {
  margin: 24px 0;
  padding: 16px;
  background-color: #f9fafb;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  text-align: center;
  position: relative;
}

.mermaid-container::before {
  content: "图表";
  position: absolute;
  top: -10px;
  left: 20px;
  background-color: #007BFF;
  color: white;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
}

.mermaid-rendered {
  margin: 0 auto;
  max-width: 100%;
  overflow-x: auto;
}

.mermaid-error {
  color: #e53e3e;
  font-weight: bold;
  padding: 10px;
  background-color: #fef2f2;
  border-radius: 4px;
}

/* 原有 Markdown 样式保持不变 */
.markdown-content h1,
.markdown-content h2,
.markdown-content h3,
.markdown-content h4,
.markdown-content h5,
.markdown-content h6 {
  margin-top: 24px;
  margin-bottom: 16px;
  font-weight: 600;
  line-height: 1.25;
}

.markdown-content h1 {
  font-size: 2em;
  border-bottom: 1px solid #eaecef;
  padding-bottom: 0.3em;
}

.markdown-content h2 {
  font-size: 1.5em;
  border-bottom: 1px solid #eaecef;
  padding-bottom: 0.3em;
}

.markdown-content h3 {
  font-size: 1.25em;
}

.markdown-content h4 {
  font-size: 1em;
}

/* 段落和列表样式 */
.markdown-content p,
.markdown-content ul,
.markdown-content ol {
  margin-top: 0;
  margin-bottom: 16px;
}

.markdown-content ul,
.markdown-content ol {
  padding-left: 2em;
}

.markdown-content li {
  margin-top: 0.25em;
}

/* 代码样式 */
.markdown-content code {
  padding: 0.2em 0.4em;
  margin: 0;
  font-size: 85%;
  background-color: rgba(27, 31, 35, 0.05);
  border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

.markdown-content pre {
  padding: 16px;
  overflow: auto;
  font-size: 85%;
  line-height: 1.45;
  background-color: #f6f8fa;
  border-radius: 3px;
  margin-top: 0;
  margin-bottom: 16px;
}

.markdown-content pre code {
  padding: 0;
  margin: 0;
  background-color: transparent;
  border: 0;
  word-break: normal;
  white-space: pre;
}

/* 表格样式 */
.markdown-content table {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 16px;
}

.markdown-content table th,
.markdown-content table td {
  padding: 6px 13px;
  border: 1px solid #dfe2e5;
}

.markdown-content table tr {
  background-color: #fff;
  border-top: 1px solid #c6cbd1;
}

.markdown-content table tr:nth-child(2n) {
  background-color: #f6f8fa;
}

/* 引用样式 */
.markdown-content blockquote {
  padding: 0 1em;
  color: #6a737d;
  border-left: 0.25em solid #dfe2e5;
  margin: 0 0 16px 0;
}

/* 水平线样式 */
.markdown-content hr {
  height: 0.25em;
  padding: 0;
  margin: 24px 0;
  background-color: #e1e4e8;
  border: 0;
}

/* 链接样式 */
.markdown-content a {
  color: #0366d6;
  text-decoration: none;
}

.markdown-content a:hover {
  text-decoration: underline;
}

/* 图片样式 */
.markdown-content img {
  max-width: 100%;
  box-sizing: border-box;
}
</style>
